// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef V8_JSON_AST_TOKEN_H_
#define V8_JSON_AST_TOKEN_H_

namespace v8 {
namespace internal {

// TOKEN_LIST takes a list of 3 macros M, all of which satisfy the
// same signature M(name, string, precedence), where name is the
// symbolic token name, string is the corresponding syntactic symbol
// (or NULL, for literals), and precedence is the precedence (or 0).
// The parameters are invoked for token categories as follows:
//
//   T: Non-keyword tokens
//   K: Keyword tokens
//   F: Future (reserved) keyword tokens

// IGNORE_TOKEN is a convenience macro that can be supplied as
// an argument (at any position) for a TOKEN_LIST call. It does
// nothing with tokens belonging to the respective category.

#define IGNORE_TOKEN(name, string, precedence)

// ----------------------------------------------------------------------------
// Nodes of the abstract syntax tree. Only concrete classes are
// enumerated here.

#define STATEMENT_TOKEN_LIST(V)                  \
  V(Block, "Block")                                      \
  V(ExpressionStatement, "ExprStmt")                        \
  V(EmptyStatement, "EmptyStmt")                             \
  V(IfStatement, "If")                                \
  V(ContinueStatement, "Continue")                          \
  V(BreakStatement, "Break")                             \
  V(ReturnStatement, "Return")                            \
  V(WithEnterStatement, "WithEnter")                         \
  V(WithExitStatement, "WithExit")                          \
  V(SwitchStatement, "Switch")                            \
  V(DoWhileStatement, "DoWhile")                           \
  V(WhileStatement, "While")                             \
  V(ForStatement, "For")                               \
  V(ForInStatement, "ForIn")                             \
  V(TryCatchStatement, "TryCatch")                          \
  V(TryFinallyStatement, "TryFinally")                        \
  V(Variable, "Var")                                 \
  V(DebuggerStatement, "Debugger")

#define EXPRESSION_TOKEN_LIST(V)                 \
  V(FunctionLiteral, "Function")                            \
  V(FunctionBoilerplateLiteral, "FuncBoil")                 \
  V(Conditional, "Conditional")                                \
  V(Slot, "Slot")                                       \
  V(VariableProxy, "Id")                              \
  V(Literal, "Literal")                                    \
  V(RegExpLiteral, "RegExp")                              \
  V(ObjectLiteral, "ObjectLiteral")                              \
  V(ArrayLiteral, "ArrayLiteral")                               \
  V(CatchExtensionObject, "CatchExt")                       \
  V(Assignment, "Assign")                                 \
  V(Throw, "Throw")                                      \
  V(Property, "Property")                                   \
  V(Call, "Call")                                       \
  V(CallNew, "CallNew")                                    \
  V(CallRuntime, "CallRuntime")                                \
  V(UnaryOperation, "UOp")                             \
  V(CountOperation, "CountOp")                             \
  V(BinaryOperation, "BinOp")                            \
  V(CompareOperation, "CompareOp")                           \
  V(ThisFunction, "ThisFunction")

#define AST_TOKEN_LIST(V)                        \
  /* End of source indicator. */                        \
  V(EOS, "EOS")                                 \
  V(Program, "Program")                                 \
  STATEMENT_TOKEN_LIST(V)                        \
  EXPRESSION_TOKEN_LIST(V)                       \
                                                                        \
  /* Identifiers (not keywords or future reserved words). */            \
  T(IDENTIFIER, "IDENTIFIER")                                                \
                                                                        \
  /* Illegal token - not able to scan. */                               \
  T(ILLEGAL, "ILLEGAL")        


class AstToken {
 public:
  // All token values.
#define T(name, string) k##name,
  enum Value {
    AST_TOKEN_LIST(T)
    NUM_TOKENS
  };
#undef T

#ifdef DEBUG
  // Returns a string corresponding to the C++ token name
  // (e.g. "LT" for the token LT).
  static const char* Name(Value tok) {
    ASSERT(0 <= tok && tok < NUM_TOKENS);
    return name_[tok];
  }
#endif

  // Predicates
  static bool IsStatement(Value tok) {
    return kBlock <= tok && tok <= kDebuggerStatement;
  }

  static bool IsExpression(Value tok) {
    return kFunctionLiteral <= tok && tok <= kThisFunction;
  }


  // Returns a string corresponding to the JS token string
  // (.e., "<" for the token LT) or NULL if the token doesn't
  // have a (unique) string (e.g. an IDENTIFIER).
  static const char* String(Value tok) {
    ASSERT(0 <= tok && tok < NUM_TOKENS);
    return string_[tok];
  }


  // Returns the keyword value if str is a keyword;
  // returns IDENTIFIER otherwise. The class must
  // have been initialized.
  static Value Lookup(const char* str);

  // Must be called once to initialize the class.
  // Multiple calls are ignored.
  static void Initialize();

 private:
#ifdef DEBUG
  static const char* name_[NUM_TOKENS];
#endif
  static const char* string_[NUM_TOKENS];
  //static int8_t precedence_[NUM_TOKENS];
};


class AstTokenAttribute {
// N.B: Attribute names must have unique first letter
 public:
  // All token values.

  //enum Value {kOp = 'o', kName = 'n', kHandle = 'h', kPos = 'p', kUnknown = 0};
  enum Value {kOp, kName, kHandle, kPos, kUnknown};
  
  static const char* String(Value tok) {
    //ASSERT(0 <= tok && tok < NUM_TOKENS);
    switch(tok) {
    case kOp : return "op";
    case kName : return "name";
    case kHandle : return "name";
    case kPos : return "pos";
    default: return "unknown";
    }
  }
  

  static Value Lookup(const char* str) {
    //return (Value) *str;
    if (str == NULL) return kUnknown;
    
    const char c = *str; // Get 1st character
    switch(c) {
    case 'o' : return kOp;
    case 'n' : return kName;
    case 'h' : return kHandle;
    case 'p' : return kPos;
    default: return kUnknown;
    }
  }

};

} }  // namespace v8::internal

#endif  // V8_JSON_AST_TOKEN_H_
